package com.oyc.demo.listener;

import java.util.ArrayList;
import java.util.List;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.oyc.demo.domain.Cablebasic;
import com.oyc.demo.domain.Exporterror;
import com.oyc.demo.easyexcel.EasyExcelValiHelper;
import com.oyc.demo.service.ExporterrorService;
import com.oyc.demo.service.TemimportService;

public class TemimportListener extends AnalysisEventListener<Cablebasic> {
	/**
	  * 每1000条处理一次，然后清理list ，方便内存回收
	  */
	private static final int BATCH_COUNT = 1000;
	
	//成功结果集
	private List<Cablebasic> successList = new ArrayList<Cablebasic>();
	//失败结果集
	private List<Exporterror> errList = new ArrayList<Exporterror>();
	//excel文件名
	private String fileName;
	
	/**
	  * 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
	  */
	private TemimportService temimportService;
	
	/**
	  * 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
	  */
	private ExporterrorService exporterrorService;
	
	 /**
	  * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
	  *
	  * @param demoDAO
	  */
	 public TemimportListener(TemimportService temimportService,ExporterrorService exporterrorService,String fileName) {
	     this.temimportService = temimportService;
	     this.exporterrorService = exporterrorService;
	     this.fileName=fileName;
	 }
	 
	 /**
	  * 所有数据解析完成了 都会来调用
	  *
	  * @param context
	  */
	@Override
	public void doAfterAllAnalysed(AnalysisContext context) {
		saveDataTemimport();
		saveDataExporterror();
	}
	
	/**
	  * 这个每一条数据解析都会来调用
	  *
	  * @param data
	  *            one row value. Is is same as {@link AnalysisContext#readRowHolder()}
	  * @param context
	  */
	@Override
	public void invoke(Cablebasic data, AnalysisContext context) {
		//如果用户填写了"预筛检-检测结果"这一列的数据，才算是有资格评判错误与正确的一行数据,没有就归为错误数据
		if(data.getFiltertestresult()==null||data.getFiltertestresult().trim().length()==0) {
			Exporterror exporterror=new Exporterror();
			exporterror.setFilename(fileName);
			exporterror.setContent("");
			exporterror.setProvincecompanyname(data.getProvincecompanyname());
			exporterror.setReelnumber(data.getReelnumber());
			exporterror.setErrortype("");
			exporterror.setRownum(data.getRownum());
			exporterror.setOrdernumber(data.getOrdernumber());
			errList.add(exporterror);
		}else{
			/**
			 *格式错误				
			 */
			String errMsg="";
			String errortype="";
			try {
	            //根据excel数据实体中的javax.validation + 正则表达式来校验excel数据
	            errMsg = EasyExcelValiHelper.validateEntity(data);
	            errortype = "格式错误"+" ";
	        } catch (NoSuchFieldException e) {
	            errMsg = "解析数据出错"+" ";
	            errortype = "格式错误"+" ";
	            e.printStackTrace();
	        }
			
			/**
			 *逻辑错误				
			 */	
			//////////////////预筛选没有填写
			if(data.getFiltertestresult()==null||data.getFiltertestresult().trim().length()==0){
				if((data.getTiptestresult()!=null&&data.getTiptestresult().trim().length()>0)||(data.getIntertestresult()!=null&&data.getIntertestresult().trim().length()>0)){
					errMsg+="预筛选检测结果没有填写，也不应填写端头检测结果或中间段检测结果;";
					errortype+="逻辑错误"+" ";
				}
			}else{
			//////////////////预筛选填写了
			//预筛选合格时
			if(data.getFiltertestresult().trim().equals("合格")){
				if((data.getTiptestresult()!=null&&data.getTiptestresult().trim().length()>0)||(data.getIntertestresult()!=null&&data.getIntertestresult().trim().length()>0)){
					errMsg+="当预筛检合格时，则该条检测合格，端头检测及中间段检测结果信息不可录入;";
					errortype+="逻辑错误"+" ";
				}
			}
			//预筛选不合格时
			if(data.getFiltertestresult().trim().equals("不合格")){
				//端头检测未录入，则不管中间段录入不录入，都进行一样的提示
				if(data.getTiptestresult()==null||data.getTiptestresult().trim().length()==0){
					errMsg+="当预筛检不合格时，则需进行端头检测结果录入;";
					errortype+="逻辑错误"+" ";
				}else{
					//端头检测不合格
					if(data.getTiptestresult().trim().equals("不合格")){
						if(data.getTestresult()==null||!data.getTestresult().trim().equals("整段不合格")){
							errMsg+="当预筛检不合格并且端头检测不合格时，应判定为整段不合格;";
							errortype+="逻辑错误"+" ";
						}
						if(data.getIntertestresult()!=null&&data.getIntertestresult().trim().length()>0){
							errMsg+="当预筛检不合格并且当端头检测不合格时，中间段检测结果信息不可录入;";
							errortype+="逻辑错误"+" ";
						}
					}
					//如果端头检测合格
					if(data.getTiptestresult().trim().equals("合格")){
						//中间段检测没有录入
						if(data.getIntertestresult()==null||data.getIntertestresult().trim().length()==0){
							errMsg+="当预筛选不合格并且端头检测合格时，则应继续中间段检测;";
							errortype+="逻辑错误"+" ";
						}else{
							//中间段合格
							if(data.getIntertestresult().trim().equals("合格")){
								//当预筛选不合格并且端头检测合格并且中间段检测合格时，则判定为预筛选结果存在问题,这里不归为逻辑错误
								data.setRemark("预筛选结果不准确");
							}
							//中间段不合格
							if(data.getIntertestresult().trim().equals("不合格")){
								if(data.getTestresult()!=null&&!data.getTestresult().trim().equals("中间段不合格")){
									errMsg+="当预筛选不合格并且端头检测合格并且中间段检测不合格时，则应判定中间段不合格;";
									errortype+="逻辑错误"+" ";
								}
							}
						}
					}
					
				}
			}
			}
			
			//加入正确数组
			if(errMsg==null||errMsg.trim().length()==0){
				//设置上文件名
				data.setFilename(fileName);
				successList.add(data);
			}
			//加入错误数组
			else{
				Exporterror exporterror=new Exporterror();
				exporterror.setFilename(fileName);
				exporterror.setContent(errMsg);
				exporterror.setProvincecompanyname(data.getProvincecompanyname());
				exporterror.setReelnumber(data.getReelnumber());
				exporterror.setErrortype(errortype);
				exporterror.setRownum(data.getRownum());
				exporterror.setOrdernumber(data.getOrdernumber());
				errList.add(exporterror);
			}
		}
		
		// 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
	     if (successList.size() >= BATCH_COUNT) {
	    	 saveDataTemimport();
	     }
	     
	     // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
	     if (errList.size() >= BATCH_COUNT) {
	    	 saveDataExporterror();
	     }
	}
	
	/**
	  * 加上存储数据库
	  */
	 private void saveDataTemimport() {
		 if(successList!=null&&successList.size()>0){
			 temimportService.insertBatch(successList);
			 successList.clear();
		 }
	 }

	 /**
	  * 加上存储数据库
	  */
	 private void saveDataExporterror() {
		 if(errList!=null&&errList.size()>0){
			 exporterrorService.insertBatch(errList);
			 errList.clear();
		 }
	 }

}
